class MyPromise {

    static STATUS_RESOLVED = "resolved";
    static STATUS_REJECTED = "rejected";
    static STATUS_PENDING = "pending";

    constructor(handler) {

        this.status = MyPromise.STATUS_PENDING
        this.data = null
        this.err = null

        /* 预备收集回调 */
        this.callbacks = []

        // 给handler以resolve和reject函数
        handler(
            MyPromise.doResolve.bind(this),
            MyPromise.doReject.bind(this)
        )

    }

    static doResolve(data) {
        setTimeout(() => {
            if (this.isCalllStackEmpty()) {
                console.log("回调栈已空！");
                return
            }

            this.status = MyPromise.STATUS_RESOLVED
            this.data = data
            this.err = null
            console.log("resolve", this.data);//resolve data from then1

            this.next()
        });
    }

    static doReject(err) {
        setTimeout(() => {
            if (this.isCalllStackEmpty()) {
                console.log("回调栈已空！");
                return
            }

            this.status = MyPromise.STATUS_REJECTED
            this.data = null
            this.err = err
            console.log("reject", this.err);

            this.next()
        });
    }

    // MyPromise.resolve(data)
    static resolve(data) {
        return new MyPromise(resolve => resolve(data))
    }

    // MyPromise.reject(err)
    static reject(err) {
        return new MyPromise((resolve, reject) => reject(err))
    }

    isCalllStackEmpty() {
        return this.callbacks.length === 0
    }

    /* 找出回调队列中首个指定type的回调并返回 不符合条件的全部弹出 */
    next() {
        // console.log("next:this.callbacks", this.callbacks);
        const targetType = this.status === MyPromise.STATUS_RESOLVED ? "then" : "catch"

        while (this.callbacks.length) {
            const { type, callback } = this.callbacks.shift()
            // console.log(`一个${type}已弹出`);

            if (type === "finally" || type === targetType) {

                try {
                    let data = callback(
                        this.status === MyPromise.STATUS_RESOLVED ? this.data : this.err
                    )

                    if (data === undefined || data.constructor !== MyPromise) {
                        // 将执行结果继续向后履约
                        MyPromise.doResolve.call(this, data)
                    } else {
                        data.callbacks = this.callbacks
                        // console.log("data.callbacks changed", data.callbacks);
                    }

                } catch (err) {
                    MyPromise.doReject.call(this, err)
                }

                break

            }
        }
    }

    then(cb) {
        // 将cb收集起来，以便将来回调
        this.callbacks.push({
            type: "then",
            callback: cb
        })

        return this
    }

    catch(cb) {
        // 将cb收集起来，以便将来回调
        this.callbacks.push({
            type: "catch",
            callback: cb
        })
        return this
    }

    finally(cb) {
        // 将cb收集起来，以便将来回调
        this.callbacks.push({
            type: "finally",
            callback: cb
        })
        return this
    }

}

module.exports = MyPromise